package client

import (
	"crypto/md5"
	"database/sql"
	"encoding/json"
	"fmt"
	"gin-epg/internal/app/dao"
	"gin-epg/internal/app/entity"
	"github.com/go-resty/resty/v2"
	"time"
)

// KKN 频道名称映射
var mapKkn = map[string]string{
	"1": "东方卫视",
	"2": "上海新闻综合",
	"3": "上海外语",
	"5": "第一财经",
	"6": "上海纪实",
	"4": "上海都市",
	"9": "哈哈炫动",
	// 更多键值对...
}

// HandleKknCron 处理 KKN 节目单
func HandleKknCron(beforeDay, afterDay int) error {
	dao.Logger.Infof("handleKknCron start")
	source := "kkn"

	client := resty.New()
	for key, value := range mapKkn {
		dao.Logger.Infof("Key: %s, Value: %s", key, value)
		for dayOffset := -beforeDay; dayOffset <= afterDay; dayOffset++ {
			urlDate := time.Now().AddDate(0, 0, dayOffset).Format("2006-01-02")
			dao.Logger.Infof(urlDate)
			url := fmt.Sprintf("https://kapi.kankanews.com/content/pc/tv/programs?channel_id=%s&date=%s", key, urlDate)
			timestampSecond := time.Now().Unix()
			toenc := fmt.Sprintf("Api-Version=v1&channel_id=%s&date=%s&nonce=fip0licp&platform=mobile&timestamp=%d&version=v2.0.0&28c8edde3d61a0411511d3b1866f0636", key, urlDate, timestampSecond)

			// 生成两次 MD5 哈希
			mdd5 := MD5(MD5(toenc))

			resp, err := client.R().
				SetHeaders(map[string]string{
					"Api-Version": "v1",
					"version":     "v2.0.0",
					"timestamp":   fmt.Sprintf("%d", timestampSecond),
					"nonce":       "fip0licp",
					"platform":    "mobile",
					"sign":        mdd5,
				}).
				Get(url)

			if err != nil {
				return fmt.Errorf("failed to get data from URL: %v", err)
			}

			var data map[string]interface{}
			if err := json.Unmarshal(resp.Body(), &data); err != nil {
				return fmt.Errorf("failed to unmarshal JSON: %v", err)
			}

			if data["code"].(string) == "1000" && data["result"] != nil {
				if programs, ok := data["result"].(map[string]interface{})["programs"].([]interface{}); ok {
					// 获取当前日期范围内的已有节目记录
					db := dao.SqlSession
					dateParsed, _ := time.Parse("2006-01-02", urlDate)
					var existingRecords []entity.EpgProgramCollect
					if err := db.Where(&entity.EpgProgramCollect{Channel: value, Date: entity.NullDate{sql.NullTime{Time: dateParsed, Valid: true}}, Source: source}).Find(&existingRecords).Error; err != nil {
						dao.Logger.Errorf("failed to get existing records: %v", err)
						continue
					}

					existingMap := make(map[string]*entity.EpgProgramCollect)
					for i := range existingRecords {
						existingMap[existingRecords[i].Start] = &existingRecords[i]
					}

					var newPrograms, updatePrograms, deletePrograms []entity.EpgProgramCollect

					for _, item := range programs {
						itemMap := item.(map[string]interface{})
						startTime := int64(itemMap["start_time"].(float64))
						stopTime := int64(itemMap["end_time"].(float64))
						title := itemMap["name"].(string)
						desc := ""

						momentStartDate := time.Unix(startTime, 0)
						momentStopDate := time.Unix(stopTime, 0)

						channel := value
						date := momentStartDate.Format("2006-01-02")
						start := momentStartDate.Format("15:04")
						stop := momentStopDate.Format("15:04")

						if channel != "" && date != "" && start != "" && stop != "" {
							if existingRecord, ok := existingMap[start]; ok {
								if existingRecord.Title != title || existingRecord.End != stop {
									existingRecord.Title = title
									existingRecord.Desc = desc
									existingRecord.End = stop
									existingRecord.UpdateTime = entity.NullTime{sql.NullTime{Time: time.Now(), Valid: true}}
									updatePrograms = append(updatePrograms, *existingRecord)
								}
								delete(existingMap, start)
							} else {
								newRecord := entity.EpgProgramCollect{
									Title:      title,
									Desc:       desc,
									Source:     source,
									Channel:    channel,
									Date:       entity.NullDate{sql.NullTime{Time: dateParsed, Valid: true}},
									Start:      start,
									End:        stop,
									CreateTime: entity.NullTime{sql.NullTime{Time: time.Now(), Valid: true}},
								}
								newPrograms = append(newPrograms, newRecord)
							}
						}
					}

					// 处理需要删除的记录
					for _, record := range existingMap {
						deletePrograms = append(deletePrograms, *record)
					}

					// 执行数据库操作
					if len(updatePrograms) > 0 {
						for _, program := range updatePrograms {
							if err := db.Model(&program).Updates(entity.EpgProgramCollect{Title: program.Title, Desc: program.Desc, End: program.End, UpdateTime: program.UpdateTime}).Error; err != nil {
								dao.Logger.Errorf("update error: %v", err)
							} else {
								dao.Logger.Debugf("update success: %v", program)
							}
						}
					}

					if len(newPrograms) > 0 {
						for _, program := range newPrograms {
							if err := db.Create(&program).Error; err != nil {
								dao.Logger.Errorf("insert error: %v", err)
							} else {
								dao.Logger.Debugf("insert success: %v", program)
							}
						}
					}

					if len(deletePrograms) > 0 {
						for _, program := range deletePrograms {
							if err := db.Delete(&program).Error; err != nil {
								dao.Logger.Errorf("delete error: %v", err)
							} else {
								dao.Logger.Debugf("delete success: %v", program)
							}
						}
					}
				}
			}
		}
	}
	return nil
}

func MD5(str string) string {
	data := []byte(str) //切片
	has := md5.Sum(data)
	md5str := fmt.Sprintf("%x", has) //将[]byte转成16进制
	return md5str
}
